package com.chat.api.web.service;

import cn.hutool.core.collection.CollUtil;
import com.chat.api.common.exception.ApiException;
import com.chat.api.utils.ResultUtil;
import com.chat.api.utils.util.IdWorkerUtil;
import com.chat.api.utils.util.ParamUtil;
import com.chat.api.web.dao.ApprovalRepo;
import com.chat.api.web.po.ApprovalBean;
import com.chat.api.web.po.BlogBean;
import com.chat.api.web.po.UserBean;
import com.chat.api.web.vo.ApprovalEntity;
import com.chat.api.web.vo.MessageEntity;
import com.google.common.collect.Lists;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.identity.User;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;

@Service
public class ApprovalService {

    @Autowired
    private ApprovalRepo approvalRepo;
    @Autowired
    private TaskService taskService;
    @Autowired
    private ProcessEngine processEngine;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private UserService userService;
    @Autowired
    private ChatService chatService;

    /**
     * 部署审批流程
     * @return
     */
    public Boolean deployProcess(String flowName) {
        Deployment deployment = repositoryService.createDeployment()
                .name(flowName)
                .addClasspathResource("processes/apply1.bpmn")
                .addClasspathResource("processes/apply1.png")
                .deploy();
        System.out.println("部署ID："+deployment.getId());//1
        System.out.println("部署时间："+deployment.getDeploymentTime());
        return true;
    }

    /**
     * 启动流程
     * @return
     * @param approvalEntity
     */
    @Transactional(readOnly = false)
    public void startApproval(ApprovalEntity approvalEntity,HttpServletRequest request) {
        UserBean userInfo = userService.findByUserInfo(request);
        approvalEntity.setId(IdWorkerUtil.getInstance().toString());
        //获取审批流程id
        Deployment de = repositoryService.createDeploymentQuery()
                .deploymentName("面试审批")
                .singleResult();
        //启动一个新的审批流程
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(de.getId()).singleResult();
        ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId());
        String processInstanceId = processInstance.getProcessInstanceId();

        //提交审批
        Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
        Map<String, Object> map = new HashMap<>();
        //将下一个审批人数据存到对象里
        map.put("inner_introduce",approvalEntity.getApprover());
        taskService.complete(task.getId(),map);
        ApprovalBean approvalBean = new ApprovalBean();
        approvalEntity.setBean(approvalBean);
        approvalBean.setApproverId(approvalEntity.getApprover());
        approvalBean.setInitiatorId(userInfo.getId());
        approvalBean.setProcInstId(processInstanceId);
        approvalBean.setCreateBy(userInfo.getId());
        approvalBean.setCreateDate(new Date());
        approvalRepo.save(approvalBean);
    }

    /**
     * @Des: 查看待办流程
     * @Author: liut
     * @Date: 2020/11/13 10:11
     */
    public String findWithDown(HttpServletRequest request, ModelMap mm){
        List<ApprovalEntity> list = Lists.newArrayList();
        UserBean userInfo = userService.findByUserInfo(request);
        List<ApprovalBean> approvalBeans = approvalRepo.findByApproverId(userInfo.getId());
        //查出所有待办流程
        for (ApprovalBean approvalBean : approvalBeans) {
            Task task = taskService.createTaskQuery().taskAssignee(approvalBean.getProcInstId()).singleResult();
            if (!approvalBean.getProcInstId().equals(task.getProcessInstanceId()))
                continue;
            ApprovalEntity entity = new ApprovalEntity();
            entity.setValue(approvalBean);
            UserBean initiator = userService.findById(approvalBean.getInitiatorId());
            entity.setInitiator(initiator.getName());
            entity.setFlowNodeName(task.getName());
            list.add(entity);
        }
        mm.addAttribute("user",userInfo);
        mm.addAttribute("list",list);
        return "/approval/approvalList.html";
    }

    /**
     * @Des: 查看流程节点详情
     * @Author: liut 
     * @Date: 2020/11/13 11:26
     */
    public String findFlowDetail(Long approvalId, ModelMap mm){
        ApprovalBean bean = approvalRepo.getOne(approvalId);
        ApprovalEntity entity = new ApprovalEntity();
        entity.setValue(bean);
        mm.addAttribute("entity",entity);
        return "/approval/form.html";
    }

    /**
     * 进行审批
     * @return
     */
    @Transactional(readOnly = false)
    public MessageEntity approval(HttpServletRequest request,ApprovalEntity approvalEntity){
        UserBean userInfo = userService.findByUserInfo(request);
        //进行流程审批
        List<Task> list = taskService.createTaskQuery().taskAssignee(userInfo.getUsername()).list();
        for (Task task : list) {
            if (!task.getProcessInstanceId().equals(approvalEntity.getProcInstId())){
                continue;
            }
            Map<String, Object> map = CollUtil.newHashMap();
            map.put("result",approvalEntity.getResult());
            map.put("score",approvalEntity.getScore());
            map.put("user",approvalEntity.getApprover());
            taskService.complete(task.getId(),map);
            //将最新数据持久化
            ApprovalBean approvalBean = new ApprovalBean();
            approvalEntity.setBean(approvalBean);
            //将下一个审批人数据存到对象里
            approvalBean.setApproverId(approvalEntity.getApprover());
            approvalBean.setUpdateBy(userInfo.getId());
            approvalBean.setUpdateDate(new Date());
            approvalRepo.save(approvalBean);//流程节点名称、开始时间、审批人、状态
        }
        return ResultUtil.success("审批完成");
    }

    /**
     * 删除审批流程
     * @param approvalEntity
     */
    @Transactional(readOnly = false)
    public MessageEntity deleteByBlogId(ApprovalEntity approvalEntity) {
        try {
            String message = "很抱歉，您的面试申请已被驳回，。。。";
            Task task = taskService.createTaskQuery().taskId(approvalEntity.getProcInstId()).singleResult();
            if (task == null) return ResultUtil.success("未找到相对应流程");
            runtimeService.deleteProcessInstance(task.getProcessInstanceId(),"终止流程");
            chatService.sendMsg(Long.parseLong(approvalEntity.getInitiator()),message);
            return ResultUtil.success("审批流程删除成功");
        }catch (Exception e){
            e.printStackTrace();
            throw new ApiException("删除审批流程异常");
        }
    }

    /**
     * 查看审批进度图
     */
    public MessageEntity getApprovalRate(Long approvalId, HttpServletResponse response) {
        try {
            ApprovalBean bean = approvalRepo.getOne(approvalId);
            if (bean == null){
                return ResultUtil.success("没有流程图可供查看");
            }
            Task task = taskService.createTaskQuery().processInstanceId(bean.getProcInstId()).singleResult();
            InputStream is =getDiagram(task.getProcessInstanceId());
            if (is == null) ResultUtil.success("没有流程图可供查看");
            response.setContentType("image/png");

            BufferedImage image = ImageIO.read(is);
            OutputStream out = response.getOutputStream();
            ImageIO.write(image, "png", out);

            is.close();
            out.close();
            return ResultUtil.success("成功");
        }catch (Exception e){
            e.printStackTrace();
            throw new ApiException("系统繁忙，请稍后再试！！！");
        }
    }

    //获取流程审批进程图
    public InputStream getDiagram(String processInstanceId) {
        //获得流程实例
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId).singleResult();
        String processDefinitionId = StringUtils.EMPTY;
        if (processInstance == null) {
            //查询已经结束的流程实例
            HistoricProcessInstance processInstanceHistory =
                    historyService.createHistoricProcessInstanceQuery()
                            .processInstanceId(processInstanceId).singleResult();
            if (processInstanceHistory == null)
                return null;
            else
                processDefinitionId = processInstanceHistory.getProcessDefinitionId();
        } else {
            processDefinitionId = processInstance.getProcessDefinitionId();
        }

        //使用宋体
        String fontName = "宋体";
        //获取BPMN模型对象
        BpmnModel model = repositoryService.getBpmnModel(processDefinitionId);
        //获取流程实例当前的节点，需要高亮显示
        List<String> currentActs = Collections.EMPTY_LIST;
        if (processInstance != null)
            currentActs = runtimeService.getActiveActivityIds(processInstance.getId());

        return processEngine.getProcessEngineConfiguration()
                .getProcessDiagramGenerator()
                .generateDiagram(model, "png", currentActs, new ArrayList<String>(),
                        fontName, fontName, fontName, null, 1.0);
    }

    /**
     * @Des: 查看审批历史记录
     * @Author: liut
     * @Date: 2020/11/13 13:34
     */
    public MessageEntity findFlowHistory(String proinstId) {
        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processInstanceId(proinstId).list();
//        for (HistoricActivityInstance hai : list) {
//            System.out.println("===========================");
//            System.out.println("任务ID:"+hai.getId());
//            System.out.println("流程实例ID:"+hai.getProcessInstanceId());
//            System.out.println("活动名称："+hai.getActivityName());
//            System.out.println("办理人："+hai.getAssignee());
//            System.out.println("开始时间："+hai.getStartTime());
//            System.out.println("结束时间："+hai.getEndTime());
//            System.out.println("===========================");
//        }
        return ResultUtil.success(list);
    }
}
